package plugin

import (
	"context"
	"fmt"
	"path/filepath"
	"sync"
)

// PluginFactory 插件工厂，支持创建不同模式的插件
type PluginFactory struct {
	wasmLoader    *WasmPluginLoader
	rpcManager    *RPCPluginManager
	pluginsByID   map[string]Plugin
	pluginsByType map[PluginType][]Plugin
	mutex         sync.RWMutex

	// 用于测试的插件创建函数，如果设置将替代默认创建行为
	createPluginFunc func(ctx context.Context, info PluginInfo) (Plugin, error)
}

// NewPluginFactory 创建新的插件工厂
func NewPluginFactory(basePath string) *PluginFactory {
	wasmPluginsDir := filepath.Join(basePath, "wasm")
	rpcPluginsDir := filepath.Join(basePath, "rpc")

	return &PluginFactory{
		wasmLoader:    NewWasmPluginLoader(wasmPluginsDir),
		rpcManager:    NewRPCPluginManager(rpcPluginsDir),
		pluginsByID:   make(map[string]Plugin),
		pluginsByType: make(map[PluginType][]Plugin),
	}
}

// RegisterPlugin 注册插件到工厂
func (f *PluginFactory) RegisterPlugin(plugin Plugin) error {
	f.mutex.Lock()
	defer f.mutex.Unlock()

	id := plugin.ID()
	if _, exists := f.pluginsByID[id]; exists {
		return fmt.Errorf("plugin with ID %s already registered", id)
	}

	pluginType := plugin.Type()
	if !f.isValidPluginType(pluginType) {
		return fmt.Errorf("invalid plugin type: %s", pluginType)
	}

	f.pluginsByID[id] = plugin
	f.pluginsByType[pluginType] = append(f.pluginsByType[pluginType], plugin)

	return nil
}

// CreatePlugin 根据插件信息创建插件实例
func (f *PluginFactory) CreatePlugin(ctx context.Context, info PluginInfo) (Plugin, error) {
	// 检查插件是否已存在
	f.mutex.RLock()
	if plugin, exists := f.pluginsByID[info.ID]; exists {
		f.mutex.RUnlock()
		return plugin, nil
	}
	f.mutex.RUnlock()

	var plugin Plugin
	var err error

	// 如果设置了测试函数，使用测试函数创建插件
	if f.createPluginFunc != nil {
		plugin, err = f.createPluginFunc(ctx, info)
	} else {
		// 使用普通逻辑创建插件
		switch info.Mode {
		case PluginModeWasm:
			plugin, err = f.createWasmPlugin(ctx, info)
		case PluginModeRPC:
			plugin, err = f.createRPCPlugin(ctx, info)
		default:
			return nil, fmt.Errorf("unsupported plugin mode: %s", info.Mode)
		}
	}

	if err != nil {
		return nil, err
	}

	// 注册新创建的插件
	if err := f.RegisterPlugin(plugin); err != nil {
		return nil, err
	}

	return plugin, nil
}

// createWasmPlugin 创建WASM插件
func (f *PluginFactory) createWasmPlugin(ctx context.Context, info PluginInfo) (Plugin, error) {
	// 构建WASM插件描述符
	descriptor := WasmPluginDescriptor{
		ID:          info.ID,
		Name:        info.Name,
		Type:        info.Type,
		Version:     info.Version,
		APIVersion:  info.APIVersion,
		Author:      info.Author,
		Description: info.Description,
		EntryPoint:  info.ID + ".wasm", // 简化处理，假设入口点是插件ID加.wasm后缀
		Config:      info.Config,
	}

	// 使用LoadWasmPlugin函数创建插件
	return LoadWasmPlugin(ctx, descriptor)
}

// createRPCPlugin 创建RPC插件
func (f *PluginFactory) createRPCPlugin(ctx context.Context, info PluginInfo) (Plugin, error) {
	// 在实际实现中，这里应该基于插件类型创建不同的RPC插件
	var plugin Plugin
	switch info.Type {
	case PluginTypeProcessor:
		plugin = NewProcessorRPCPlugin(info.ID, info.Name, info.Version, info.Description)
	default:
		plugin = NewRPCPluginImpl(info.ID, info.Name, info.Version, info.Description)
	}

	// 初始化插件
	if err := plugin.Init(ctx, &PluginConfig{
		ID:          info.ID,
		Name:        info.Name,
		Description: info.Description,
		Type:        info.Type,
		Version:     info.Version,
		Config:      info.Config,
	}); err != nil {
		return nil, fmt.Errorf("failed to initialize RPC plugin: %w", err)
	}

	return plugin, nil
}

// DiscoverPlugins 发现并加载所有插件
func (f *PluginFactory) DiscoverPlugins(ctx context.Context) ([]Plugin, error) {
	var allPlugins []Plugin

	// 加载WASM插件
	wasmPlugins, err := f.wasmLoader.LoadWasmPlugins(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to load WASM plugins: %w", err)
	}

	// 加载RPC插件
	rpcPlugins, err := f.rpcManager.LoadPlugins(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to load RPC plugins: %w", err)
	}

	// 注册所有插件
	for _, plugin := range append(wasmPlugins, rpcPlugins...) {
		if err := f.RegisterPlugin(plugin); err != nil {
			fmt.Printf("Failed to register plugin %s: %v\n", plugin.ID(), err)
			continue
		}
		allPlugins = append(allPlugins, plugin)
	}

	return allPlugins, nil
}

// GetPlugin 根据ID获取插件
func (f *PluginFactory) GetPlugin(id string) (Plugin, error) {
	f.mutex.RLock()
	defer f.mutex.RUnlock()

	plugin, exists := f.pluginsByID[id]
	if !exists {
		return nil, fmt.Errorf("plugin with ID %s not found", id)
	}

	return plugin, nil
}

// GetPluginsByType 获取指定类型的所有插件
func (f *PluginFactory) GetPluginsByType(pluginType PluginType) []Plugin {
	f.mutex.RLock()
	defer f.mutex.RUnlock()

	return f.pluginsByType[pluginType]
}

// CreatePluginFromFile 从插件描述文件创建插件
func (f *PluginFactory) CreatePluginFromFile(ctx context.Context, filePath string) (Plugin, error) {
	// 获取文件扩展名
	ext := filepath.Ext(filePath)

	switch ext {
	case ".json":
		// 读取WASM插件描述符
		descriptor, err := f.wasmLoader.readPluginDescriptor(filePath)
		if err != nil {
			return nil, fmt.Errorf("failed to read plugin descriptor: %w", err)
		}

		// 设置WASM文件路径
		descriptor.WasmPath = filepath.Join(filepath.Dir(filePath), descriptor.EntryPoint)

		// 创建并初始化插件
		plugin, err := LoadWasmPlugin(ctx, descriptor)
		if err != nil {
			return nil, fmt.Errorf("failed to initialize plugin: %w", err)
		}

		// 注册插件
		if err := f.RegisterPlugin(plugin); err != nil {
			return nil, err
		}

		return plugin, nil

	case ".wasm":
		// 直接从WASM文件创建插件，这里简化处理
		id := filepath.Base(filePath)
		id = id[:len(id)-len(ext)] // 移除扩展名

		descriptor := WasmPluginDescriptor{
			ID:          id,
			Name:        id,
			Type:        PluginTypeProcessor, // 默认为处理器插件
			Version:     "1.0.0",             // 默认版本
			Description: "WASM plugin",
			EntryPoint:  filepath.Base(filePath),
			WasmPath:    filePath,
			Config:      make(map[string]interface{}),
		}

		// 创建并初始化插件
		plugin, err := LoadWasmPlugin(ctx, descriptor)
		if err != nil {
			return nil, fmt.Errorf("failed to initialize plugin: %w", err)
		}

		// 注册插件
		if err := f.RegisterPlugin(plugin); err != nil {
			return nil, err
		}

		return plugin, nil

	default:
		// 检查是否为可执行文件（RPC插件）
		fileInfo, err := f.rpcManager.LoadPlugin(ctx, filePath)
		if err != nil {
			return nil, fmt.Errorf("unsupported plugin file type: %s", ext)
		}

		// 注册插件
		if err := f.RegisterPlugin(fileInfo); err != nil {
			return nil, err
		}

		return fileInfo, nil
	}
}

// CreateExamplePlugins 创建示例插件
func (f *PluginFactory) CreateExamplePlugins(ctx context.Context) error {
	// 创建WASM示例插件
	if err := f.wasmLoader.CreateExampleWasmPlugin(f.wasmLoader.pluginsDir); err != nil {
		return fmt.Errorf("failed to create example WASM plugin: %w", err)
	}

	// 创建RPC示例插件
	if err := CreateExampleRPCPlugin(f.rpcManager.pluginsDir); err != nil {
		return fmt.Errorf("failed to create example RPC plugin: %w", err)
	}

	return nil
}

// isValidPluginType 检查插件类型是否有效
func (f *PluginFactory) isValidPluginType(pluginType PluginType) bool {
	switch pluginType {
	case PluginTypeProcessor,
		PluginTypeConnector,
		PluginTypeMonitor,
		PluginTypeWASM,
		PluginTypeRPC,
		PluginTypeGo,
		PluginTypeProcess:
		return true
	default:
		return false
	}
}
